#include "lib/lock.h"
#include "lib/print.h"
#include "proc/cpu.h"
#include "riscv.h"

// 中断嵌套管理的 push_off 函数：负责关中断
void push_off(void)
{
    int old = intr_get();  // 获取当前中断状态
    intr_off();  // 禁用中断
    if (mycpu()->noff == 0) {
        mycpu()->origin = old;  // 保存中断状态
    }
    mycpu()->noff += 1;  // 记录进入的嵌套层数
}

// 中断嵌套管理的 pop_off 函数：负责恢复中断
void pop_off(void)
{
    if (intr_get())  // 确保中断已关闭
        panic("pop_off: interrupts enabled");

    if (mycpu()->noff < 1)  // 确保计数正确
        panic("pop_off: no interrupts disabled");

    mycpu()->noff -= 1;  // 减少嵌套层数
    if (mycpu()->noff == 0 && mycpu()->origin) {
        intr_on();  // 恢复中断
    }
}

// 检查自旋锁是否被当前 CPU 持有
bool spinlock_holding(spinlock_t *lk)
{
    return lk->locked && (lk->cpuid == mycpuid());
}

// 初始化自旋锁
void spinlock_init(spinlock_t *lk, char *name)
{
    lk->name = name;
    lk->locked = 0;
    // 这里需要注意！ 声明cpuid需要初始化为一个不可能的值，比如-1，置为0代表的是NULL，是不可行的。
    lk->cpuid = -1;  // 未被任何 CPU 持有
}

// 获取自旋锁
void spinlock_acquire(spinlock_t *lk)
{
    push_off();  // 禁用中断，防止死锁
    if (spinlock_holding(lk))  // 确保未重复获取锁
        panic("spinlock_acquire: lock already held");

    // 自旋直到获取锁
    while (__sync_lock_test_and_set(&lk->locked, 1) != 0)
        ;

    __sync_synchronize();  // 确保内存操作不会被重排
    lk->cpuid = mycpuid();  // 记录持有锁的 CPU
}

// 释放自旋锁
void spinlock_release(spinlock_t *lk)
{
    if (!spinlock_holding(lk))  // 确保当前 CPU 持有该锁
        panic("spinlock_release: lock not held");

    lk->cpuid = -1;  // 重置 CPU ID
    __sync_synchronize();  // 确保释放锁之前的操作完成
    __sync_lock_release(&lk->locked);  // 释放锁

    pop_off();  // 恢复中断
}